home *** CD-ROM | disk | FTP | other *** search
/ CrystalVision Software Se… Wiki Wonder - Wikipedia / CrystalVision Software Services 703: The Wiki Wonder - Wikipedia.iso / 0703 / Business / CodeX Apps / CodeX.exe / CodeX / html / lib / Web 2.0 / JavaScripts / slider.js < prev   
Encoding:
JavaScript  |  2006-09-05  |  11.0 KB  |  294 lines

  1. // script.aculo.us slider.js v1.6.4, Wed Sep 06 11:30:58 CEST 2006
  2.  
  3. // Copyright (c) 2005 Marty Haught, Thomas Fuchs 
  4. //
  5. // See http://script.aculo.us for more info
  6. // 
  7. // Permission is hereby granted, free of charge, to any person obtaining
  8. // a copy of this software and associated documentation files (the
  9. // "Software"), to deal in the Software without restriction, including
  10. // without limitation the rights to use, copy, modify, merge, publish,
  11. // distribute, sublicense, and/or sell copies of the Software, and to
  12. // permit persons to whom the Software is furnished to do so, subject to
  13. // the following conditions:
  14. // 
  15. // The above copyright notice and this permission notice shall be
  16. // included in all copies or substantial portions of the Software.
  17. //
  18. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  19. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  20. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  21. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  22. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  23. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  24. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  25.  
  26. if(!Control) var Control = {};
  27. Control.Slider = Class.create();
  28.  
  29. // options:
  30. //  axis: 'vertical', or 'horizontal' (default)
  31. //
  32. // callbacks:
  33. //  onChange(value)
  34. //  onSlide(value)
  35. Control.Slider.prototype = {
  36.   initialize: function(handle, track, options) {
  37.     var slider = this;
  38.     
  39.     if(handle instanceof Array) {
  40.       this.handles = handle.collect( function(e) { return $(e) });
  41.     } else {
  42.       this.handles = [$(handle)];
  43.     }
  44.     
  45.     this.track   = $(track);
  46.     this.options = options || {};
  47.  
  48.     this.axis      = this.options.axis || 'horizontal';
  49.     this.increment = this.options.increment || 1;
  50.     this.step      = parseInt(this.options.step || '1');
  51.     this.range     = this.options.range || $R(0,1);
  52.     
  53.     this.value     = 0; // assure backwards compat
  54.     this.values    = this.handles.map( function() { return 0 });
  55.     this.spans     = this.options.spans ? this.options.spans.map(function(s){ return $(s) }) : false;
  56.     this.options.startSpan = $(this.options.startSpan || null);
  57.     this.options.endSpan   = $(this.options.endSpan || null);
  58.  
  59.     this.restricted = this.options.restricted || false;
  60.  
  61.     this.maximum   = this.options.maximum || this.range.end;
  62.     this.minimum   = this.options.minimum || this.range.start;
  63.  
  64.     // Will be used to align the handle onto the track, if necessary
  65.     this.alignX = parseInt(this.options.alignX || '0');
  66.     this.alignY = parseInt(this.options.alignY || '0');
  67.     
  68.     this.trackLength = this.maximumOffset() - this.minimumOffset();
  69.  
  70.     this.handleLength = this.isVertical() ? 
  71.       (this.handles[0].offsetHeight != 0 ? 
  72.         this.handles[0].offsetHeight : this.handles[0].style.height.replace(/px$/,"")) : 
  73.       (this.handles[0].offsetWidth != 0 ? this.handles[0].offsetWidth : 
  74.         this.handles[0].style.width.replace(/px$/,""));
  75.  
  76.     this.active   = false;
  77.     this.dragging = false;
  78.     this.disabled = false;
  79.  
  80.     if(this.options.disabled) this.setDisabled();
  81.  
  82.     // Allowed values array
  83.     this.allowedValues = this.options.values ? this.options.values.sortBy(Prototype.K) : false;
  84.     if(this.allowedValues) {
  85.       this.minimum = this.allowedValues.min();
  86.       this.maximum = this.allowedValues.max();
  87.     }
  88.  
  89.     this.eventMouseDown = this.startDrag.bindAsEventListener(this);
  90.     this.eventMouseUp   = this.endDrag.bindAsEventListener(this);
  91.     this.eventMouseMove = this.update.bindAsEventListener(this);
  92.  
  93.     // Initialize handles in reverse (make sure first handle is active)
  94.     this.handles.each( function(h,i) {
  95.       i = slider.handles.length-1-i;
  96.       slider.setValue(parseFloat(
  97.         (slider.options.sliderValue instanceof Array ? 
  98.           slider.options.sliderValue[i] : slider.options.sliderValue) || 
  99.          slider.range.start), i);
  100.       Element.makePositioned(h); // fix IE
  101.       Event.observe(h, "mousedown", slider.eventMouseDown);
  102.     });
  103.     
  104.     Event.observe(this.track, "mousedown", this.eventMouseDown);
  105.     Event.observe(document, "mouseup", this.eventMouseUp);
  106.     Event.observe(document, "mousemove", this.eventMouseMove);
  107.     
  108.     this.initialized = true;
  109.   },
  110.   dispose: function() {
  111.     var slider = this;    
  112.     Event.stopObserving(this.track, "mousedown", this.eventMouseDown);
  113.     Event.stopObserving(document, "mouseup", this.eventMouseUp);
  114.     Event.stopObserving(document, "mousemove", this.eventMouseMove);
  115.     this.handles.each( function(h) {
  116.       Event.stopObserving(h, "mousedown", slider.eventMouseDown);
  117.     });
  118.   },
  119.   setDisabled: function(){
  120.     this.disabled = true;
  121.   },
  122.   setEnabled: function(){
  123.     this.disabled = false;
  124.   },  
  125.   getNearestValue: function(value){
  126.     if(this.allowedValues){
  127.       if(value >= this.allowedValues.max()) return(this.allowedValues.max());
  128.       if(value <= this.allowedValues.min()) return(this.allowedValues.min());
  129.       
  130.       var offset = Math.abs(this.allowedValues[0] - value);
  131.       var newValue = this.allowedValues[0];
  132.       this.allowedValues.each( function(v) {
  133.         var currentOffset = Math.abs(v - value);
  134.         if(currentOffset <= offset){
  135.           newValue = v;
  136.           offset = currentOffset;
  137.         } 
  138.       });
  139.       return newValue;
  140.     }
  141.     if(value > this.range.end) return this.range.end;
  142.     if(value < this.range.start) return this.range.start;
  143.     return value;
  144.   },
  145.   setValue: function(sliderValue, handleIdx){
  146.     if(!this.active) {
  147.       this.activeHandleIdx = handleIdx || 0;
  148.       this.activeHandle    = this.handles[this.activeHandleIdx];
  149.       this.updateStyles();
  150.     }
  151.     handleIdx = handleIdx || this.activeHandleIdx || 0;
  152.     if(this.initialized && this.restricted) {
  153.       if((handleIdx>0) && (sliderValue<this.values[handleIdx-1]))
  154.         sliderValue = this.values[handleIdx-1];
  155.       if((handleIdx < (this.handles.length-1)) && (sliderValue>this.values[handleIdx+1]))
  156.         sliderValue = this.values[handleIdx+1];
  157.     }
  158.     sliderValue = this.getNearestValue(sliderValue);
  159.     this.values[handleIdx] = sliderValue;
  160.     this.value = this.values[0]; // assure backwards compat
  161.     
  162.     this.handles[handleIdx].style[this.isVertical() ? 'top' : 'left'] = 
  163.       this.translateToPx(sliderValue);
  164.     
  165.     this.drawSpans();
  166.     if(!this.dragging || !this.event) this.updateFinished();
  167.   },
  168.   setValueBy: function(delta, handleIdx) {
  169.     this.setValue(this.values[handleIdx || this.activeHandleIdx || 0] + delta, 
  170.       handleIdx || this.activeHandleIdx || 0);
  171.   },
  172.   translateToPx: function(value) {
  173.     return Math.round(
  174.       ((this.trackLength-this.handleLength)/(this.range.end-this.range.start)) * 
  175.       (value - this.range.start)) + "px";
  176.   },
  177.   translateToValue: function(offset) {
  178.     return ((offset/(this.trackLength-this.handleLength) * 
  179.       (this.range.end-this.range.start)) + this.range.start);
  180.   },
  181.   getRange: function(range) {
  182.     var v = this.values.sortBy(Prototype.K); 
  183.     range = range || 0;
  184.     return $R(v[range],v[range+1]);
  185.   },
  186.   minimumOffset: function(){
  187.     return(this.isVertical() ? this.alignY : this.alignX);
  188.   },
  189.   maximumOffset: function(){
  190.     return(this.isVertical() ? 
  191.       (this.track.offsetHeight != 0 ? this.track.offsetHeight :
  192.         this.track.style.height.replace(/px$/,"")) - this.alignY : 
  193.       (this.track.offsetWidth != 0 ? this.track.offsetWidth : 
  194.         this.track.style.width.replace(/px$/,"")) - this.alignY);
  195.   },  
  196.   isVertical:  function(){
  197.     return (this.axis == 'vertical');
  198.   },
  199.   drawSpans: function() {
  200.     var slider = this;
  201.     if(this.spans)
  202.       $R(0, this.spans.length-1).each(function(r) { slider.setSpan(slider.spans[r], slider.getRange(r)) });
  203.     if(this.options.startSpan)
  204.       this.setSpan(this.options.startSpan,
  205.         $R(0, this.values.length>1 ? this.getRange(0).min() : this.value ));
  206.     if(this.options.endSpan)
  207.       this.setSpan(this.options.endSpan, 
  208.         $R(this.values.length>1 ? this.getRange(this.spans.length-1).max() : this.value, this.maximum));
  209.   },
  210.   setSpan: function(span, range) {
  211.     if(this.isVertical()) {
  212.       span.style.top = this.translateToPx(range.start);
  213.       span.style.height = this.translateToPx(range.end - range.start + this.range.start);
  214.     } else {
  215.       span.style.left = this.translateToPx(range.start);
  216.       span.style.width = this.translateToPx(range.end - range.start + this.range.start);
  217.     }
  218.   },
  219.   updateStyles: function() {
  220.     this.handles.each( function(h){ Element.removeClassName(h, 'selected') });
  221.     Element.addClassName(this.activeHandle, 'selected');
  222.   },
  223.   startDrag: function(event) {
  224.     if(Event.isLeftClick(event)) {
  225.       if(!this.disabled){
  226.         this.active = true;
  227.         
  228.         var handle = Event.element(event);
  229.         var pointer  = [Event.pointerX(event), Event.pointerY(event)];
  230.         var track = handle;
  231.         if(track==this.track) {
  232.           var offsets  = Position.cumulativeOffset(this.track); 
  233.           this.event = event;
  234.           this.setValue(this.translateToValue( 
  235.            (this.isVertical() ? pointer[1]-offsets[1] : pointer[0]-offsets[0])-(this.handleLength/2)
  236.           ));
  237.           var offsets  = Position.cumulativeOffset(this.activeHandle);
  238.           this.offsetX = (pointer[0] - offsets[0]);
  239.           this.offsetY = (pointer[1] - offsets[1]);
  240.         } else {
  241.           // find the handle (prevents issues with Safari)
  242.           while((this.handles.indexOf(handle) == -1) && handle.parentNode) 
  243.             handle = handle.parentNode;
  244.         
  245.           this.activeHandle    = handle;
  246.           this.activeHandleIdx = this.handles.indexOf(this.activeHandle);
  247.           this.updateStyles();
  248.         
  249.           var offsets  = Position.cumulativeOffset(this.activeHandle);
  250.           this.offsetX = (pointer[0] - offsets[0]);
  251.           this.offsetY = (pointer[1] - offsets[1]);
  252.         }
  253.       }
  254.       Event.stop(event);
  255.     }
  256.   },
  257.   update: function(event) {
  258.    if(this.active) {
  259.       if(!this.dragging) this.dragging = true;
  260.       this.draw(event);
  261.       // fix AppleWebKit rendering
  262.       if(navigator.appVersion.indexOf('AppleWebKit')>0) window.scrollBy(0,0);
  263.       Event.stop(event);
  264.    }
  265.   },
  266.   draw: function(event) {
  267.     var pointer = [Event.pointerX(event), Event.pointerY(event)];
  268.     var offsets = Position.cumulativeOffset(this.track);
  269.     pointer[0] -= this.offsetX + offsets[0];
  270.     pointer[1] -= this.offsetY + offsets[1];
  271.     this.event = event;
  272.     this.setValue(this.translateToValue( this.isVertical() ? pointer[1] : pointer[0] ));
  273.     if(this.initialized && this.options.onSlide)
  274.       this.options.onSlide(this.values.length>1 ? this.values : this.value, this);
  275.   },
  276.   endDrag: function(event) {
  277.     if(this.active && this.dragging) {
  278.       this.finishDrag(event, true);
  279.       Event.stop(event);
  280.     }
  281.     this.active = false;
  282.     this.dragging = false;
  283.   },  
  284.   finishDrag: function(event, success) {
  285.     this.active = false;
  286.     this.dragging = false;
  287.     this.updateFinished();
  288.   },
  289.   updateFinished: function() {
  290.     if(this.initialized && this.options.onChange) 
  291.       this.options.onChange(this.values.length>1 ? this.values : this.value, this);
  292.     this.event = null;
  293.   }
  294. }